package com.jxpanda.spring.module.pay.core.pojo.wechat;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.jxpanda.infrastructure.core.constant.StringConstant;
import com.jxpanda.infrastructure.core.tollkit.StringKit;
import com.jxpanda.infrastructure.core.tollkit.json.JsonKit;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;

/**
 * @author Panda
 */
public class WechatPayRequest {

    @Data
    public static class CloseOrder {
        @JsonProperty("mchid")
        private String mchId;
    }

    /**
     * 统一下单入参数据
     */
    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    public static class UnifiedOrder {
        @JsonProperty("appid")
        private String appId;
        @JsonProperty("mchid")
        private String mchId;
        @JsonProperty("description")
        private String description;
        @JsonProperty("out_trade_no")
        private String outTradeNo;
        @JsonProperty("notify_url")
        private String notifyUrl;
        @JsonProperty("amount")
        private WechatPayAmount.UnifiedOrderAmount amount;
        @JsonProperty("attach")
        private String attach;
        @JsonProperty("payer")
        private WechatPayer payer;

        public UnifiedOrder(String openId, String orderId, String description, BigDecimal amount) {
            this(openId, orderId, description, amount, null, null);
        }

        public UnifiedOrder(String openId, String orderId, String description, BigDecimal amount, Object attach) {
            this(openId, orderId, description, amount, attach, null);
        }

        public UnifiedOrder(String openId, String outTradeNo, String description, BigDecimal amount, Object attach, String notifyUrl) {
            this.payer = new WechatPayer(openId);
            this.outTradeNo = outTradeNo;
            this.description = description;
            this.amount = WechatPayAmount.unifiedOrderAmount(amount);
            if (ObjectUtils.isEmpty(attach)) {
                this.attach = StringConstant.BLANK;
            } else if (attach instanceof String) {
                this.attach = (String) attach;
            } else {
                this.attach = JsonKit.toJson(attach);
            }
            this.notifyUrl = notifyUrl;
        }


        public UnifiedOrder fillProperties(String appId, String mchId, String notifyUrl) {
            this.appId = appId;
            this.mchId = mchId;
            if (StringKit.isBlank(this.notifyUrl)) {
                this.notifyUrl = notifyUrl;
            }
            return this;
        }
    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public static class Refund {
        @JsonProperty("transaction_id")
        private String transactionId;
        @JsonProperty("out_trade_no")
        private String outTradeNo;
        @JsonProperty("out_refund_no")
        private String outRefundNo;
        @JsonProperty("reason")
        private String reason;
        @JsonProperty("notify_url")
        private String notifyUrl;
        @JsonProperty("amount")
        private WechatPayAmount.RefundAmount amount;
    }


    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public static class Callback {
        @JsonProperty("id")
        private String id;
        @JsonProperty("create_time")
        private String createTime;
        @JsonProperty("event_type")
        private String eventType;
        @JsonProperty("resource")
        private Callback.Resource resource;
        @JsonProperty("resource_type")
        private String resourceType;
        @JsonProperty("summary")
        private String summary;

        @Data
        @NoArgsConstructor
        @AllArgsConstructor
        public static class Resource {
            @JsonProperty("algorithm")
            private String algorithm;
            @JsonProperty("associated_data")
            private String associatedData;
            @JsonProperty("ciphertext")
            private String ciphertext;
            @JsonProperty("nonce")
            private String nonce;
            @JsonProperty("original_type")
            private String originalType;
        }

        public boolean isPaySuccess() {
            return TRANSACTION_SUCCESS.equals(this.getEventType());
        }

        public boolean isRefundSuccess() {
            return REFUND_SUCCESS.equals(this.getEventType());
        }

        /**
         * 支付成功通知
         */
        public static final String TRANSACTION_SUCCESS = "TRANSACTION.SUCCESS";
        /**
         * 退款成功通知
         */
        public static final String REFUND_SUCCESS = "REFUND.SUCCESS";
        /**
         * 退款异常通知
         */
        public static final String REFUND_ABNORMAL = "REFUND.ABNORMAL";
        /**
         * 退款关闭通知
         */
        public static final String REFUND_CLOSED = "REFUND.CLOSED";

    }

}
